﻿/*
** Xin YUAN, 2021, BSD (2)
*/

////////////////////////////////////////////////////////////////////////////////

#include "base/_sys_process.h"

////////////////////////////////////////////////////////////////////////////////

//sub_process
/*! \brief A class for sub-process.

A class for sub-process.
*/
class sub_process
{
public:
	/*! \brief Constructor.

	Constructor.
	*/
	sub_process() noexcept
	{
	}
	sub_process(const sub_process&) = delete;
	sub_process(sub_process&& src) noexcept : m_process(rv_forward(src.m_process))
	{
	}
	/*! \brief Destructor.

	Destructor.
	*/
	~sub_process() noexcept
	{
	}

	sub_process& operator=(const sub_process&) = delete;
	sub_process& operator=(sub_process&& src) noexcept
	{
		m_process = rv_forward(src.m_process);
		return *this;
	}

	bool Create(const char_s* szCmd) noexcept
	{
		m_process.SetStartupFlags(FALSE);
		return m_process.Create(szCmd, FALSE, NULL, CREATE_NO_WINDOW) ? true : false;
	}
	bool CheckRunning() noexcept
	{
		DWORD dwRet = m_process.GetState();
		return dwRet == WAIT_TIMEOUT;
	}
	void Terminate() noexcept
	{
		m_process.Terminate();
	}
	void WaitForEnd() noexcept
	{
		m_process.WaitForEnd();
	}
	int32_t GetExitCode() const noexcept
	{
		return (int32_t)m_process.GetExitCode();
	}
	void Reset() noexcept
	{
		m_process.CloseProcessHandles();
	}

protected:
	_w_child_process m_process;
};

//rio_process
/*! \brief A class for redirecting IO process.

A class for redirecting IO process.
*/
class rio_process
{
public:
	/*! \brief Constructor.

	Constructor.
	*/
	rio_process() noexcept
	{
	}
	rio_process(const rio_process&) = delete;
	rio_process(rio_process&& src) noexcept : m_process(rv_forward(src.m_process))
	{
	}
	/*! \brief Destructor.

	Destructor.
	*/
	~rio_process() noexcept
	{
	}

	rio_process& operator=(const rio_process&) = delete;
	rio_process& operator=(rio_process&& src) noexcept
	{
		m_process = rv_forward(src.m_process);
		return *this;
	}

	bool Create(const char_s* szCmd) noexcept
	{
		m_process.SetStartupFlags(FALSE);
		return m_process.Create(szCmd, NULL, CREATE_NO_WINDOW) ? true : false;
	}
	bool ReadFromPipe(void* pData, uint32_t uSize, uint32_t& uRead) noexcept
	{
		DWORD dwRead;
		BOOL bRet = m_process.ReadFromPipe(pData, uSize, &dwRead);
		uRead = dwRead;
		return bRet ? true : false;
	}
	bool WriteToPipe(const void* pData, uint32_t uSize, uint32_t& uWritten) noexcept
	{
		DWORD dwWritten;
		BOOL bRet = m_process.WriteToPipe(pData, uSize, &dwWritten);
		uWritten = dwWritten;
		return bRet ? true : false;
	}
	void Terminate() noexcept
	{
		m_process.Terminate();
	}
	void WaitForEnd() noexcept
	{
		m_process.WaitForEnd();
	}
	int32_t GetExitCode() const noexcept
	{
		return (int32_t)m_process.GetExitCode();
	}
	void Reset() noexcept
	{
		m_process.ClosePipeStdout();
		m_process.ClosePipeStdin();
		m_process.CloseProcessHandles();
	}

protected:
	_w_rio_process m_process;
};

////////////////////////////////////////////////////////////////////////////////
